import { isBoolean, isFunction } from 'lodash-es';
import type { ComputedRef } from 'vue';

import type { PaginationProps } from '../types/pagination';
import { APISETTING } from '../const';

import type { BasicTableProps } from '@/components/table/src/props';
import { handleTree } from '@/utils/ruoyi';

export function useDataSource(
  propsRef: ComputedRef<BasicTableProps>,
  getPaginationInfo: ComputedRef<boolean | PaginationProps>,
  setPagination: (info: PaginationProps) => void,
  setLoading: (loading: boolean) => void,
  emit: any,
) {
  const dataSourceRef = ref<Recordable[]>([]);
  const tableData = ref<Recordable[]>([]);

  watchEffect(() => {
    tableData.value = unref(dataSourceRef);
  });

  watch(
    () => unref(propsRef).dataSource,
    () => {
      const { dataSource }: any = unref(propsRef);
      dataSource && (dataSourceRef.value = dataSource);
    },
    {
      immediate: true,
    },
  );

  const getDataSourceRef = computed(() => {
    const dataSource = unref(dataSourceRef);
    if (!dataSource || dataSource.length === 0) {
      return [];
    }
    return unref(dataSourceRef);
  });

  async function fetch(opt?: any) {
    try {
      setLoading(true);
      const {
        request,
        pagination,
        beforeRequest,
        afterRequest,
        treeTable,
        treeField,
        treeParentField,
        treeChildrenField,
      }: any = unref(propsRef);

      if (!request) {
        return;
      }

      // 组装分页信息
      const pageField = APISETTING.pageField;
      const sizeField = APISETTING.sizeField;
      const itemCount = APISETTING.countField;
      let listField = APISETTING.listField;

      if (pagination) {
        listField = 'rows';
      }

      let pageParams: Recordable = {};
      const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;

      if (isBoolean(pagination) && !pagination) {
        pageParams = {};
      } else {
        pageParams[pageField] = (opt && opt[pageField]) || page;
        pageParams[sizeField] = pageSize;
      }

      const params = {
        ...pageParams,
        ...opt,
      };

      if (beforeRequest && isFunction(beforeRequest)) {
        // eslint-disable-next-line prefer-rest-params
        beforeRequest.call(undefined, ...arguments);
      }

      const res = await request(params);
      const total = res[itemCount];
      let resultInfo = res[listField] ? res[listField] : [];

      if (afterRequest && isFunction(afterRequest)) {
        // eslint-disable-next-line prefer-rest-params
        afterRequest.call(undefined, ...arguments);
      }

      if (treeTable) {
        resultInfo = handleTree(resultInfo, treeField, treeParentField, treeChildrenField);
      }

      dataSourceRef.value = resultInfo;

      // 设置分页信息
      if ((isBoolean(pagination))) {
        setPagination({
          itemCount: total,
        });
      }

      emit('fetch-success', {
        items: unref(resultInfo),
        total,
      });
    } catch (error) {
      emit('fetch-error', error);
      dataSourceRef.value = [];
    } finally {
      setLoading(false);
    }
  }

  /**
   * 监听请求参数变化, 自动请求
   */
  watch(() => propsRef.value.requestParams, async value => {
    await reload(value);
  });

  onMounted(() => {
    setTimeout(() => {
      fetch();
    }, 16);
  });

  function setTableData(values: Recordable[]) {
    dataSourceRef.value = values;
  }

  function getTableData(): any[] {
    return getDataSourceRef.value;
  }

  async function reload(opt?: any) {
    await fetch(opt);
  }

  return {
    fetch,
    getDataSourceRef,
    reload,
    setTableData,
    getTableData,
  };
}
